package play;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

public class PlayScript {

    public static void main(String[] args) {

        String script = null;
        Map params = null;
        try {
            params = parseParams(args);
        } catch (Exception e) {
            e.printStackTrace();
        }

        boolean help = params.containsKey("help") ? (boolean) params.get("help") : false;
        if (help) {
            showHelp();
            return;
        }
        //从源代码读取脚本
        String scriptFile = params.containsKey("scriptFile") ? (String) params.get("scriptFile") : null;
        if (scriptFile != null) {
            try {
                script = readTextFIle(scriptFile);
            } catch (IOException e) {
                System.out.println("unable to read from : " + scriptFile);
                return;
            }
        }

        //是否生成汇编代码
        boolean genAsm = params.containsKey("genAsm") ? (Boolean) params.get("genAsm") : false;

        //是否生成字节码
        boolean genByteCode = params.containsKey("genByteCode") ? (Boolean) params.get("genByteCode") : false;

        //打印编译过程中的信息
        boolean verbose = params.containsKey("verbose") ? (Boolean) params.get("verbose") : false;

        //打印AST
        boolean ast_dump = params.containsKey("ast_dump") ? (Boolean) params.get("ast_dump") : false;

        //进入REPL
        if (script == null) {
            REPL(verbose, ast_dump);
        }

        //生成汇编代码
        //生成Java字节码

        //执行脚本
        PlayScriptCompiler compiler = new PlayScriptCompiler();
        AnnotatedTree at = compiler.compile(script, verbose, ast_dump);
        if (at.hasCompilationError()) {
            Object result = compiler.Execute(at);
            System.out.println(result);
        }

    }

    private static void REPL(boolean verbose, boolean ast_dump) {
    }

    /**
     * 读文本文件
     *
     * @param pathName
     * @return
     * @throws IOException
     */
    private static String readTextFIle(String pathName) throws IOException {
        StringBuffer buffer = new StringBuffer();
        try (FileReader reader = new FileReader(pathName)) {
            BufferedReader br = new BufferedReader(reader);
            String line;
            while ((line = br.readLine()) != null) {
                buffer.append(line).append("\n");
            }
        }
        return buffer.toString();
    }

    private static Map parseParams(String[] args) throws Exception {
        Map<String, Object> params = new HashMap<>();

        for (int i = 0; i < args.length; i++) {
            if (args[i].equals("-S")) {
                //输出汇编代码
                params.put("genAsm", true);
            } else if (args[i].equals("-bc")) {
                //生成字节码
                params.put("genByteCOde", true);
            } else if (args[i].equals("-h") || args[i].equals("-help")) {
                params.put("help", true);
            } else if (args[i].equals("-v")) {
                //显示作用域和符号
                params.put("verbose", true);
            } else if (args[i].equals("-ast-dump")) {
                //显示ast tree
                params.put("ast_dump", true);
            } else if (args[i].equals("-0")) {
                if (i + 1 < args.length) {
                    //outputFile = args[++i];  //让i的序号增加一个
                    params.put("outputFile", args[++i]);
                } else {
                    throw new Exception("Expecting a filename after -o");
                }
            } else if (args[i].startsWith("-")) {
                throw new Exception("Unknow parameter : " + args[i]);
            } else {
                params.put("scriptFile", args[i]);
            }
        }
        return params;
    }

    /**
     * 打印帮助信息
     */
    private static void showHelp() {
        System.out.println("usage: java play.PlayScript [-h | --help | -o outputfile | -S | -bc | -v | -ast-dump] [scriptfile]");

        System.out.println("\t-h or --help : print this help information");
        System.out.println("\t-v verbose mode : dump AST and symbols");
        System.out.println("\t-ast-dump : dump AST in lisp style");
        System.out.println("\t-o outputfile : file pathname used to save generated code, eg. assembly code");
        System.out.println("\t-S : compile to assembly code");
        System.out.println("\t-bc : compile to java byte code");
        System.out.println("\tscriptfile : file contains playscript code");

        System.out.println("\nexamples:");
        System.out.println("\tjava play.PlayScript");
        System.out.println("\t>>interactive REPL mode");
        System.out.println();

        System.out.println("\tjava play.PlayScript -v");
        System.out.println("\t>>enter REPL with verbose mode, dump ast and symbols");
        System.out.println();

        System.out.println("\tjava play.PlayScript scratch.play");
        System.out.println("\t>>compile and execute scratch.play");
        System.out.println();

        System.out.println("\tjava play.PlayScript -v scratch.play");
        System.out.println("\t>>compile and execute scratch.play in verbose mode, dump ast and symbols");
        System.out.println();

        System.out.println("\tjava play.PlayScript -bc scratch.play");
        System.out.println("\t>>compile to bytecode, save as DefaultPlayClass.class and run it");
        System.out.println();
    }

}
